var TeXHelperInputMethod = InputMethod.extend({
	helping: false,
	target_list: 'ShiftNum', // FIXME: ShiftNum should have problem...
	candlist: null,
	suggest_list: null,
	suggest_html_list: null,

	constructor: function()
	{
	},
	IMName: function()
	{
		return 'TeXHelper';
	},
	GetLanguage: function()
	{
		return 'math';
	},
	SuggestionType: function()
	{
		return 'TeX';
	},
	onActive: function()
	{
		helping = false;
	},
	onDeactive: function()
	{
	},
	PreviewURL: function(tex,title)
	{
		var ttex = '\\small{' + tex + '}';

		if(!title) title = tex;

		return "<img alt=\"" + tex + "\" title=\"" + title + "\" src=\"http://ajaxime.com/cgi-bin/mimetex.cgi?" + encodeURI(ttex) + "\" />";
	},
	UpdatePreviewImage: function()
	{
		// This should only occurs when user is in internal buffer mode...
		if(this.ime.IsInternalBufferAvailable()) {
			var text = this.ime.internalwin.GetBuffer();
			this.ime.SetPreeditText(this.PreviewURL(text));
		}
	},
	EnterHelping: function()
	{
		this.helping = true;
		this.ime.ResetPreedit();
		this.ime.AppendPreedit("\\","\\");
		Debug.present && Debug.trace(1,"TexHelperInputMethod: Enter Helping mode.");
	},
	CancelHelping: function()
	{
		this.helping = false;
		this.ime.ResetPreedit();
		this.UpdatePreviewImage();
		Debug.present && Debug.trace(1,"TexHelperInputMethod: Leave Helping mode.")
	},
	ListSelectHandler: function(obj,pos)
	{
		var len = this.ime.GetPreeditLength();
		var out = this.suggest_list[pos];
		
		out = out.substring(len);
		this.ime.SendString(obj,out);
		this.suggest_list = null;
		this.CancelHelping();
		return true;
	},
	UpdateCandidate: function()
	{
		var x = this;

		if(this.helping) {
			if(this.candlist) {
				this.candlist.UpdateList(this.suggest_html_list);
			}
			else {
				this.candlist = this.ime.candwin.OccupyList(this,this.target_list);
				if(!this.candlist) return;

				this.candlist.SetList(null,this.suggest_html_list,function(obj,pos) { return x.ListSelectHandler(obj,pos); });
				this.candlist.SetCancelHandler(function() { x.candlist = null; return true; });
			}
			this.ime.candwin.SetStatus(null);
		}
		else {
			this.ime.candwin.ReleaseList(this,this.target_list);
			this.candlist = null;
		}
		this.ime.candwin.UpdateCandidate();
	},
	GenerateSuggest: function()
	{
		if(this.helping) {
			if(this.ime.GetPreeditLength() > 1) {
				var preedit = this.ime.GetPreedit();
				var list,key,entry,html,c;
				
				preedit = preedit.substring(1);
				this.suggest_list = new Array();
				this.suggest_html_list = new Array();
				list = TeXHelperInputMethod.cmddict.find(preedit);
				c = 0;
				for(key in list) {
					entry = list[key];
					html = "\\" + key + '&nbsp;';
					if(entry.i) {
						if(entry.i.substr) html += this.PreviewURL(entry.i,entry.e);
						else html += this.PreviewURL("\\" + key,entry.e);
					}
					this.suggest_list.push("\\" + key);
					this.suggest_html_list.push(html);
					c++;
				}
				if(c==0) {
					this.suggest_list = null;
					this.suggest_html_list = null;
				}
			}
			this.UpdateCandidate();
		}
	},
	keydown_handler: function(obj,key,m)
	{
		if(!GownFullBrowserDetect.backspace_keypress && key == 8) { // backspace
			if(this.helping) {
				this.ime.DeletePreedit(1,1);
				if(this.ime.GetPreeditLength() == 0) this.CancelHelping();
				else {
					this.GenerateSuggest();
				}
			}
		}
		return true;
	},
	keypress_handler: function(obj,key,m)
	{
		var ch = String.fromCharCode(key);

		if(ch == "\\") {
			if(this.helping) {
				this.ime.ResetPreedit();
			}
			else this.EnterHelping();
		}
		else if(ch == ' ' || ch == '{' || ch == '}' || ch == '_' || ch == '^') {
			if(this.helping) this.CancelHelping();
		}
		else if(GownFullBrowserDetect.backspace_keypress && key == 8) { // backspace
			if(this.helping) {
				this.ime.DeletePreedit(1,1);
				if(this.ime.GetPreeditLength() == 0) this.CancelHelping();
				else {
					this.GenerateSuggest();
				}
			}
		}
		else if(32 <= key && key <= 125) {
			if(this.helping) {
				this.ime.AppendPreedit(ch,ch);
				this.GenerateSuggest();
			}
			else this.UpdatePreviewImage();
		}
		return true;
	}
},{
	cmddict: null,
	init: function()
	{
		this.cmddict = new GFTreeDict;
		var s = this.cmddict;

		s.push('addcontentsline',{i:null,e:null});
		s.push('addtocontents',{i:null,e:null});
		s.push('addtocounter',{i:null,e:null});
		s.push('address',{i:null,e:null});
		s.push('addtolength',{i:null,e:null});
		s.push('addvspace',{i:null,e:null});
		s.push('alph',{i:null,e:null});
		s.push('appendix',{i:null,e:null});
		s.push('arabic',{i:null,e:null});
		s.push('author',{i:null,e:null});
		s.push('backslash',{i:null,e:null});
		s.push('baselineskip',{i:null,e:null});
		s.push('baselinestretch',{i:null,e:null});
		s.push('bf',{i:null,e:null});
		s.push('bibitem',{i:null,e:null});
		s.push('bigskip',{i:null,e:null});
		s.push('boldmath',{i:null,e:null});
		s.push('cal',{i:null,e:null});
		s.push('caption',{i:null,e:null});
		s.push('cdots',{i:null,e:null});
		s.push('centering',{i:null,e:null});
		s.push('circle',{i:null,e:null});
		s.push('cite',{i:null,e:null});
		s.push('cleardoublepage',{i:null,e:null});
		s.push('clearpage',{i:null,e:null});
		s.push('cline',{i:null,e:null});
		s.push('closing',{i:null,e:null});
		s.push('dashbox',{i:null,e:null});
		s.push('date',{i:null,e:null});
		s.push('ddots',{i:null,e:null});
		s.push('dotfill',{i:null,e:null});
		s.push('em',{i:null,e:null});
		s.push('ensuremath',{i:null,e:null});
		s.push('fbox',{i:null,e:null});
		s.push('flushbottom',{i:null,e:null});
		s.push('fnsymbol',{i:null,e:null});
		s.push('footnote',{i:null,e:null});
		s.push('footnotemark',{i:null,e:null});
		s.push('footnotesize',{i:null,e:null});
		s.push('footnotetext',{i:null,e:null});
		s.push('frame',{i:null,e:null});
		s.push('framebox',{i:null,e:null});
		s.push('frenchspacing',{i:null,e:null});
		s.push('hfill',{i:null,e:null});
		s.push('hline',{i:null,e:null});
		s.push('hrulefill',{i:null,e:null});
		s.push('hspace',{i:null,e:null});
		s.push('huge',{i:null,e:null});
		s.push('Huge',{i:null,e:null});
		s.push('hyphenation',{i:null,e:null});
		s.push('include',{i:null,e:null});
		s.push('includeonly',{i:null,e:null});
		s.push('indent',{i:null,e:null});
		s.push('input',{i:null,e:null});
		s.push('it',{i:null,e:null});
		s.push('item',{i:null,e:null});
		s.push('kill',{i:null,e:null});
		s.push('label',{i:null,e:null});
		s.push('large',{i:null,e:null});
		s.push('Large',{i:null,e:null});
		s.push('LARGE',{i:null,e:null});
		s.push('ldots',{i:null,e:null});
		s.push('left',{i:null,e:null});
		s.push('lefteqn',{i:null,e:null});
		s.push('line',{i:null,e:null});
		s.push('linebreak',{i:null,e:null});
		s.push('linethickness',{i:null,e:null});
		s.push('linewidth',{i:null,e:null});
		s.push('location',{i:null,e:null});
		s.push('makebox',{i:null,e:null});
		s.push('maketitle',{i:null,e:null});
		s.push('markboth',{i:null,e:null});
		s.push('mathcal',{i:null,e:null});
		s.push('mathop',{i:null,e:null});
		s.push('mbox',{i:null,e:null});
		s.push('medskip',{i:null,e:null});
		s.push('multicolumn',{i:null,e:null});
		s.push('multiput',{i:null,e:null});
		s.push('newcommand',{i:null,e:null});
		s.push('newcounter',{i:null,e:null});
		s.push('newenvironment',{i:null,e:null});
		s.push('newfont',{i:null,e:null});
		s.push('newlength',{i:null,e:null});
		s.push('newline',{i:null,e:null});
		s.push('newpage',{i:null,e:null});
		s.push('newsavebox',{i:null,e:null});
		s.push('newtheorem',{i:null,e:null});
		s.push('nocite',{i:null,e:null});
		s.push('noindent',{i:null,e:null});
		s.push('nolinebreak',{i:null,e:null});
		s.push('normalsize',{i:null,e:null});
		s.push('nopagebreak',{i:null,e:null});
		s.push('onecolumn',{i:null,e:null});
		s.push('opening',{i:null,e:null});
		s.push('oval',{i:null,e:null});
		s.push('overbrace',{i:null,e:null});
		s.push('overline',{i:null,e:null});
		s.push('pagebreak',{i:null,e:null});
		s.push('pagenumbering',{i:null,e:null});
		s.push('pageref',{i:null,e:null});
		s.push('pagestyle',{i:null,e:null});
		s.push('par',{i:null,e:null});
		s.push('parbox',{i:null,e:null});
		s.push('parindent',{i:null,e:null});
		s.push('parskip',{i:null,e:null});
		s.push('protect',{i:null,e:null});
		s.push('providecommand',{i:null,e:null});
		s.push('put',{i:null,e:null});
		s.push('raggedbottom',{i:null,e:null});
		s.push('raggedleft',{i:null,e:null});
		s.push('raggedright',{i:null,e:null});
		s.push('raisebox',{i:null,e:null});
		s.push('ref',{i:null,e:null});
		s.push('renewcommand',{i:null,e:null});
		s.push('right',{i:null,e:null});
		s.push('rm',{i:null,e:null});
		s.push('roman',{i:null,e:null});
		s.push('rule',{i:null,e:null});
		s.push('savebox',{i:null,e:null});
		s.push('sbox',{i:null,e:null});
		s.push('sc',{i:null,e:null});
		s.push('scriptsize',{i:null,e:null});
		s.push('setcounter',{i:null,e:null});
		s.push('setlength',{i:null,e:null});
		s.push('settowidth',{i:null,e:null});
		s.push('sf',{i:null,e:null});
		s.push('shortstack',{i:null,e:null});
		s.push('signature',{i:null,e:null});
		s.push('sl',{i:null,e:null});
		s.push('small',{i:null,e:null});
		s.push('smallskip',{i:null,e:null});
		s.push('stackrel',{i:null,e:null});
		s.push('tableofcontents',{i:null,e:null});
		s.push('telephone',{i:null,e:null});
		s.push('textwidth',{i:null,e:null});
		s.push('textheight',{i:null,e:null});
		s.push('thanks',{i:null,e:null});
		s.push('thispagestyle',{i:null,e:null});
		s.push('tiny',{i:null,e:null});
		s.push('title',{i:null,e:null});
		s.push('tt',{i:null,e:null});
		s.push('twocolumn',{i:null,e:null});
		s.push('typeout',{i:null,e:null});
		s.push('typein',{i:null,e:null});
		s.push('underbrace',{i:null,e:null});
		s.push('underline',{i:null,e:null});
		s.push('unitlength',{i:null,e:null});
		s.push('usebox',{i:null,e:null});
		s.push('usecounter',{i:null,e:null});
		s.push('value',{i:null,e:null});
		s.push('vdots',{i:null,e:null});
		s.push('vector',{i:null,e:null});
		s.push('verb',{i:null,e:null});
		s.push('vfill',{i:null,e:null});
		s.push('vline',{i:null,e:null});
		s.push('vphantom',{i:null,e:null});
		s.push('vspace',{i:null,e:null});

		// commands/symbols that have images...
		s.push('sin',{i:'\\sin',e:'Function: Sine'});
		s.push('cos',{i:'\\cos',e:'Function: Cosine'});
		s.push('tan',{i:'\\tan',e:'Funciton: Tangent'});
		s.push('arcsin',{i:'\\arcsin',e:'Function: Arc-Sine'});
		s.push('arccos',{i:'\\arccos',e:'Function: Arc-Cosine'});
		s.push('arctan',{i:'\\arctan',e:'Function: Arc-Tangent'});

		s.push('frac',{i:'\\frac{?}{?}',e:'Symbol: Fraction'});
		s.push('int',{i:true,e:'Symbol: Integration Sign'});
		s.push('lim',{i:true,e:'Symbol: Integration Sign'});
		s.push('int',{i:true,e:'Symbol: Integration Sign'});

		s.push('not',{i:true,e:null});
		s.push('sqrt',{i:'\\sqrt{?}',e:'Symbol: Square root sign'});
		s.push('today',{i:true,e:'Misc: Output today date'});
		// FIXME: Include all TeX commands
		// FIXME: Later development, use different dictionary in different mode.
		//        e.g. in mimeTeX, only show mimeTeX command
		//             in BibTex, only show BibTeX command

		Debug.present && Debug.trace(0,'TexHelperInputMethod: loaded %d command(s).',s.count);
	}
});
